Spring Security3源码分析(14)-SessionManagementFilter分析-下

很多spring security3资料在介绍session的并发控制都要求配置HttpSessionEventPublisher的监听器,如下 
Xml代码   收藏代码
  1.     <listener>  
  2.         <listener-class>  
  3. org.springframework.security.web.session.HttpSessionEventPublisher  
  4.          </listener-class>  
  5.     </listener>  

这个监听器实现了HttpSessionListener接口,主要监听sessionCreated、sessionDestroyed事件。看源码 
Java代码   收藏代码
  1. public class HttpSessionEventPublisher implements HttpSessionListener {  
  2.     private static final Log log = LogFactory.getLog(HttpSessionEventPublisher.class);  
  3.     ApplicationContext getContext(ServletContext servletContext) {  
  4.         return WebApplicationContextUtils.getWebApplicationContext(servletContext);  
  5.     }  
  6.   
  7.     public void sessionCreated(HttpSessionEvent event) {  
  8.         HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event.getSession());  
  9.   
  10.         if (log.isDebugEnabled()) {  
  11.             log.debug("Publishing event: " + e);  
  12.         }  
  13.         //通过ApplicationContext的事件发布机制发布sessionCreated事件  
  14.         getContext(event.getSession().getServletContext()).publishEvent(e);  
  15.     }  
  16.   
  17.     public void sessionDestroyed(HttpSessionEvent event) {  
  18.         HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event.getSession());  
  19.   
  20.         if (log.isDebugEnabled()) {  
  21.             log.debug("Publishing event: " + e);  
  22.         }  
  23.         //通过ApplicationContext的事件发布机制发布sessionDestroyed事件  
  24.         getContext(event.getSession().getServletContext()).publishEvent(e);  
  25.     }  
  26. }  

由于ApplicationContext继承了ApplicationEventPublisher接口,所以ApplicationContext具有发布事件的能力。 
Spring中与事件有关的接口和类主要包括ApplicationEvent、ApplicationListener。 
定义一个事件的类需要继承ApplicationEvent或者ApplicationContextEvent抽象类。针对一种事件,需要特定的监听器,监听器需要实现ApplicationListener接口。当监听器接收到一个事件的时候,就会执行它的 onApplicationEvent()方法。 

上面的代码仅仅发布了session事件,针对session事件,谁去监听并处理呢? 
spring security中监听session事件的类是SessionRegistryImpl(org.springframework.security.core.session.SessionRegistryImpl) 
这个类实现了ApplicationListener<SessionDestroyedEvent>接口,但是这个类在哪里注册到ioc容器中的呢。 
如果看完上一篇的分析,应该知道是解析标签 concurrency-control 时创建这个bean并注册到ioc容器的。如果没有配置这个标签,这个类的bean就不会产生。 

接着看SessionRegistryImpl类中的处理事件的方法onApplicationEvent 
Java代码   收藏代码
  1. //实际上SessionRegistryImpl仅仅处理SessionDestroyedEvent  
  2. //接收到session失效事件,从当前缓存中清除SessionInformation  
  3. public void onApplicationEvent(SessionDestroyedEvent event) {  
  4.     String sessionId = event.getId();  
  5.     removeSessionInformation(sessionId);  
  6. }  
  7. //根据失效的sessionid清除SessionInformation对象  
  8. public void removeSessionInformation(String sessionId) {  
  9.     Assert.hasText(sessionId, "SessionId required as per interface contract");  
  10.   
  11.     SessionInformation info = getSessionInformation(sessionId);  
  12.   
  13.     if (info == null) {  
  14.         return;  
  15.     }  
  16.     //从sessionIds中清除SessionInformation  
  17.     sessionIds.remove(sessionId);  
  18.   
  19.     Set<String> sessionsUsedByPrincipal = principals.get(info.getPrincipal());  
  20.   
  21.     if (sessionsUsedByPrincipal == null) {  
  22.         return;  
  23.     }  
  24.     //从principals清除SessionInformation对应的认证实体信息  
  25.     synchronized (sessionsUsedByPrincipal) {  
  26.         sessionsUsedByPrincipal.remove(sessionId);  
  27.   
  28.         if (sessionsUsedByPrincipal.size() == 0) {  
  29.             principals.remove(info.getPrincipal());  
  30.         }  
  31.     }  
  32. }  


现在,HttpSessionEventPublisher监听器的目的就很明显了。这个过滤器首先监听session失效的事件(web容器配置的timeout、直接调用session.invalidate方法),然后由SessionRegistryImpl处理session失效事件,从自己维护的集合缓存中清除已经失效的session信息以及session对应的认证实体信息,避免造成oom。 

这里要重点区分下,上一篇分析的ConcurrentSessionFilter过滤器也是处理session失效,但是它所处理的仅仅封装后的SessionInformation类,如果这个类满足失效条件,再执行session.invalidate强制失效。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值